package com.zmn.plat.business.impl.base.phenomenon;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zmn.common.dto.VtDTO;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.plat.business.interfaces.base.phenomenon.PhenomenonBService;
import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.common.util.StringToArrayUtil;
import com.zmn.plat.model.entity.base.phenomenon.*;
import com.zmn.plat.model.entity.servcategory.ServAssCategoryQuery;
import com.zmn.plat.model.vo.base.phenomenon.PhenomenonFaultVO;
import com.zmn.plat.model.vo.base.phenomenon.PhenomenonMaintainVO;
import com.zmn.plat.model.vo.base.phenomenon.PhenomenonVO;
import com.zmn.plat.model.vo.servcategory.ServAssCategoryVO;
import com.zmn.plat.services.interfaces.base.phenomenon.PhenomenonFaultService;
import com.zmn.plat.services.interfaces.base.phenomenon.PhenomenonMaintainService;
import com.zmn.plat.services.interfaces.base.phenomenon.PhenomenonService;
import com.zmn.plat.services.interfaces.servcategory.ServAssCategoryService;
import com.zmn.plat.utils.bean.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述: 故障现象业务实现类
 *
 * @author chengguang
 * @since 2021/11/19 9:56
 */
@Slf4j
@Service
public class PhenomenonBServiceImpl implements PhenomenonBService {

    /**
     * office2003
     */
    public static final String OFFICE_EXCEL_2003_POSTFIX = ".xls";
    /**
     * office2007及以上
     */
    public static final String OFFICE_EXCEL_2007_POSTFIX = ".xlsx";

    @Resource
    private PhenomenonService phenomenonService;

    @Resource
    private PhenomenonFaultService phenomenonFaultService;

    @Resource
    private PhenomenonMaintainService phenomenonMaintainService;

    @Resource
    private ServAssCategoryService servAssCategoryService;

    @Override
    public List<Phenomenon> listEfficientPhenomenonByServCategIdAndCategTwoId(Integer servCategId, Integer categTwoId) {
        if (NumberUtil.isNullOrZero(servCategId) || NumberUtil.isNullOrZero(categTwoId)) {
            log.error("PhenomenonBServiceImpl.listEfficientPhenomenonByServCategIdAndCategTwoId入参为空,servCategId={},categTwoId={}", servCategId, categTwoId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        // 查询服务类型-产品分类关联
        List<ServAssCategoryVO> servAssCategories = servAssCategoryService.listByQuery(ServAssCategoryQuery.builder()
                .servCategId(servCategId)
                .categId(categTwoId).build());
        if (CollectionUtil.isNullOrEmpty(servAssCategories)) {
            log.error("PhenomenonBServiceImpl.listEfficientPhenomenonByServCategIdAndCategTwoId未查到服务类型-产品分类关联,servCategId={},categTwoId={}", servCategId, categTwoId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_RESULT_NULL);
        }
        ServAssCategoryVO servAssCategoryVO = servAssCategories.get(0);
        String phenomenon = servAssCategoryVO.getFault();
        if (StringUtil.isBlank(phenomenon)) {
            return Collections.emptyList();
        }
        List<Integer> phenIds = StringToArrayUtil.convertStrsToList(phenomenon);
        if (CollectionUtil.isNullOrEmpty(phenIds)) {
            return Collections.emptyList();
        }
        // 查询故障现象 过滤停用状态故障现象
        List<Phenomenon> phenomena = phenomenonService.listByIds(phenIds);
        return phenomena.stream().filter(e -> Objects.equals(com.zmn.common.constant.GlobalConsts.YES, e.getStatus())).collect(Collectors.toList());
    }

    @Override
    @Cacheable(cacheNames = "redis10m", key = "'base:listEfficientPhenomenonByFaultIds:faultIds:'+#p0", unless = "#result == null")
    public List<Phenomenon> listEfficientPhenomenonByFaultIds(List<Integer> faultIds) {
        if (CollectionUtil.isNullOrEmpty(faultIds)) {
            log.error("PhenomenonBServiceImpl.listEfficientPhenomenonByFaultIds入参为空,faultIds={}", faultIds);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        // 根据故障现象id 查询故障现象-具体故障关联
        List<PhenomenonFault> phenomenonFaults = phenomenonFaultService.listByQuery(PhenomenonFaultQuery.builder().faultIds(faultIds).build());
        if (CollectionUtil.isNullOrEmpty(phenomenonFaults)) {
            return Collections.emptyList();
        }
        // 根据故障现象-具体故障关联获取全部故障现象ids
        List<Integer> phenIds = phenomenonFaults.stream().map(PhenomenonFault::getPhenId).distinct().collect(Collectors.toList());
        if (CollectionUtil.isNullOrEmpty(phenIds)) {
            return Collections.emptyList();
        }
        // 查询全部有效故障现象详情
        List<Phenomenon> phenomenonList = phenomenonService.listByIds(phenIds);
        return phenomenonList.stream().filter(e -> Objects.equals(GlobalConsts.YES, e.getStatus())).collect(Collectors.toList());
    }

    @Override
    public List<VtDTO> listPhenomenonByPhenIds(List<Integer> phenIds) {
        if (CollectionUtil.isNullOrEmpty(phenIds)) {
            log.error("PhenomenonBServiceImpl.listPhenomenonByPhenIds入参为空,phenIds={}", phenIds);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        List<Phenomenon> phenomena = phenomenonService.listByIds(phenIds);
        if (CollectionUtil.isNullOrEmpty(phenomena)) {
            log.error("PhenomenonBServiceImpl.listPhenomenonByPhenIds未查到故障现象,phenIds={}", phenIds);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_RESULT_NULL);
        }
        List<VtDTO> vtList = new ArrayList<>();
        phenomena.forEach(e -> vtList.add(new VtDTO(e.getPhenId(), e.getPhenName(), e.getStatus())));
        return vtList;
    }

    @Override
    public List<PhenomenonVO> listPagePhenomenonByQuery(PhenomenonQuery query) {
        List<PhenomenonVO> phenomenonVos = phenomenonService.listPagePhenomenonByQuery(query);
        List<Integer> phenIds = phenomenonVos.stream().map(PhenomenonVO::getPhenId).collect(Collectors.toList());
        if (CollectionUtil.isNullOrEmpty(phenIds)) {
            return phenomenonVos;
        }
        // 关联的故障
        List<PhenomenonFaultVO> phenomenonFaultVOS = phenomenonFaultService.listFaultNameAndIdByphenIds(phenIds);
        Map<Integer, String> phenomenonFaultMap = phenomenonFaultVOS.stream()
                .collect(Collectors.toMap(PhenomenonFaultVO::getPhenId, PhenomenonFaultVO::getFaultNameAndId));
        // 关联的检修项目
        List<PhenomenonMaintainVO> phenomenonMaintainVOS = phenomenonMaintainService.listMaintainNameAndIdByphenIds(phenIds);
        Map<Integer, String> phenomenonMaintainMap = phenomenonMaintainVOS.stream()
                .collect(Collectors.toMap(PhenomenonMaintainVO::getPhenId, PhenomenonMaintainVO::getMaintainNameAndId));
        // 组装故障现象
        return phenomenonVos.stream().peek(item -> {
            item.setMaintainAndIds(phenomenonMaintainMap.get(item.getPhenId()));
            item.setFaultNameAndIds(phenomenonFaultMap.get(item.getPhenId()));
        }).collect(Collectors.toList());
    }

    @Override
    public List<PhenomenonFault> listPhenomenonFault(PhenomenonFaultQuery phenManageQuery) {
        return phenomenonFaultService.listByQuery(phenManageQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRelateFault(List<PhenomenonFault> phenomenonFaults) {
        //1、关联故障前删除原本关联的故障
        Integer phenId = phenomenonFaults.get(0).getPhenId();
        phenomenonFaultService.deleteByPhenId(phenId);
        //2、关联故障
        phenomenonFaultService.insertBatch(phenomenonFaults);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPhenomenonMaintain(List<PhenomenonMaintain> phenomenonMaintains) {
        //1、关联检修项目前删除原本关联的检修项目
        Integer phenId = phenomenonMaintains.get(0).getPhenId();
        phenomenonMaintainService.deleteByPhenId(phenId);
        //2、关联检修项目
        phenomenonMaintainService.insertBatch(phenomenonMaintains);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO importExcel(MultipartFile file, Integer operatorId, String operator, String ip) {
        InputStream inputStream = null;
        Workbook work = null;
        try {
            inputStream = file.getInputStream();
            String fileName = file.getOriginalFilename();
            work = getWorkbook(inputStream, fileName);
            if (work == null) {
                return ResponseDTO.fail("Excel工作薄为空");
            }
            Sheet okrValueSheet = work.getSheetAt(1);
            int rowNum = okrValueSheet.getLastRowNum();
            if (rowNum > 1000) {
                return ResponseDTO.fail("一次只能导入1000条数据！");
            }
            String okrValueMsg = verifyOkrValueSheet(okrValueSheet, operator).toString();
            JSONObject jsonObject = new JSONObject();
            if (StringUtil.isNotBlank(okrValueMsg)) {
                jsonObject.put("methodMsg", okrValueMsg);
                return ResponseDTO.fail(555, JSON.toJSONString(jsonObject));
            }
            //关闭相关流
            work.close();
            inputStream.close();
            //保存目标数据
            return ResponseDTO.success("操作成功");
        } catch (Exception e) {
            log.error("处理导入的excel出现异常={}", e);
            return ResponseDTO.fail("处理excel文件失败");
        } finally {
            try {
                if (work != null) {
                    work.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception ex2) {
                log.error("关闭流出现异常={}", ex2);
            }
        }

    }

    /**
     * 后端判断文件格式方式，其实这部分前端已经做过了判断，但是需求要求前后端均要判断
     *
     * @param inStr
     * @param fileName
     * @return
     * @throws Exception
     */
    public Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {

        Workbook workbook = null;
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        if (OFFICE_EXCEL_2003_POSTFIX.equals(fileType)) {
            workbook = new HSSFWorkbook(inStr);
        } else if (OFFICE_EXCEL_2007_POSTFIX.equals(fileType)) {
            workbook = new XSSFWorkbook(inStr);
        } else {
            throw new Exception("请上传excel文件！");
        }
        return workbook;
    }

    /**
     * 验证目标值Sheet
     *
     * @param okrValueSheet
     * @return
     */
    private StringBuilder verifyOkrValueSheet(Sheet okrValueSheet, String operator) {
        int getLastRowNum = okrValueSheet.getLastRowNum();
        Row row = null;
        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder insideMsg = null;
        List<Phenomenon> listPhenomenon = new ArrayList<>();
        List<PhenomenonFault> listPhenomenonFault = new ArrayList<>();
        List<PhenomenonMaintain> listPhenomenonMaintain = new ArrayList<>();
        for (int i = 2; i <= getLastRowNum; i++) {
            Phenomenon phenomenon = new Phenomenon();
            PhenomenonFault phenomenonFault = new PhenomenonFault();
            PhenomenonMaintain phenomenonMaintain = new PhenomenonMaintain();
            //取出Sheet
            try {
                insideMsg = new StringBuilder();
                row = okrValueSheet.getRow(i);
                Integer id = StringUtil.isBlank(FileUtil.getCellValue(row.getCell(2))) ? null : Integer.valueOf(FileUtil.getCellValue(row.getCell(2)));
                String title = FileUtil.getCellValue(row.getCell(3));
                if (StringUtil.isBlank(title)) {
                    buildMsg(insideMsg, "序号[" + id + "]【故障现象名称】不能为空！");
                }
                if (title.length() > 20) {
                    buildMsg(insideMsg, "序号[" + id + "]【【故障现象名称】只能输入20个字符！");
                }
                phenomenon.setPhenName(title);
                Integer phenId = StringUtil.isBlank(FileUtil.getCellValue(row.getCell(4))) ? null : Integer.valueOf(FileUtil.getCellValue(row.getCell(4)));
                if (NumberUtil.isNullOrZero(phenId)) {
                    buildMsg(insideMsg, "序号[" + id + "]【ID】不能为空！");
                }
                phenomenon.setPhenId(phenId);
                Integer maintainTime = StringUtil.isBlank(FileUtil.getCellValue(row.getCell(5))) ? null : Integer.valueOf(FileUtil.getCellValue(row.getCell(5)));
                if (NumberUtil.isNullOrZero(maintainTime)) {
                    buildMsg(insideMsg, "序号[" + id + "]【检修时长】不能为空！");
                }
                phenomenon.setMaintainTime(maintainTime);
                String faultName = FileUtil.getCellValue(row.getCell(6));
                if (StringUtil.isBlank(faultName)) {
                    buildMsg(insideMsg, "序号[" + id + "]【关联故障名称】不能为空！");
                }
                phenomenonFault.setFaultName(faultName);
                Integer faultId = StringUtil.isBlank(FileUtil.getCellValue(row.getCell(7))) ? null : Integer.valueOf(FileUtil.getCellValue(row.getCell(7)));
                if (NumberUtil.isNullOrZero(faultId)) {
                    buildMsg(insideMsg, "序号[" + id + "]【关联故障ID】不能为空！");
                }
                phenomenonFault.setFaultId(faultId);
                phenomenonFault.setPhenId(phenId);

                String maintainName = FileUtil.getCellValue(row.getCell(8));
                if (StringUtil.isBlank(maintainName)) {
                    buildMsg(insideMsg, "序号[" + id + "]【关联检修项目名称】不能为空！");
                }
                phenomenonMaintain.setMaintainName(maintainName);
                Integer maintainId = StringUtil.isBlank(FileUtil.getCellValue(row.getCell(9))) ? null : Integer.valueOf(FileUtil.getCellValue(row.getCell(9)));
                if (NumberUtil.isNullOrZero(maintainId)) {
                    buildMsg(insideMsg, "序号[" + id + "]【关联检修项目ID】不能为空！");
                }
                phenomenonMaintain.setMaintainId(maintainId);
                phenomenonMaintain.setPhenId(phenId);
                String status = FileUtil.getCellValue(row.getCell(10));
                if (StringUtil.isBlank(status)) {
                    buildMsg(insideMsg, "序号[" + id + "]【状态】不能为空！");
                }
                phenomenon.setStatus(Objects.equals("启用", status) ? 2 : 1);
                Integer sort = StringUtil.isBlank(FileUtil.getCellValue(row.getCell(11))) ? null : Integer.valueOf(FileUtil.getCellValue(row.getCell(11)));
                phenomenon.setSort(NumberUtil.isNullOrZero(sort) ? 0 : sort);
                phenomenon.setCreater(operator);
                phenomenon.setCreateTime(DateUtil.getNow());
                phenomenon.setUpdater(operator);
                phenomenon.setUpdateTime(DateUtil.getNow());
                phenomenonMaintain.setCreater(operator);
                phenomenonMaintain.setCreateTime(DateUtil.getNow());
                phenomenonMaintain.setUpdater(operator);
                phenomenonMaintain.setUpdateTime(DateUtil.getNow());
                phenomenonFault.setCreater(operator);
                phenomenonFault.setCreateTime(DateUtil.getNow());
                phenomenonFault.setUpdater(operator);
                phenomenonFault.setUpdateTime(DateUtil.getNow());

                if (insideMsg.length() > 0) {
                    stringBuilder.append("第[" + (i + 1) + "]行" + insideMsg + "</br>");
                    continue;
                }
                final long count = listPhenomenon.stream().filter(x -> Objects.equals(x.getPhenId(), phenId)).count();
                if (NumberUtil.isNullOrZero(count)) {
                    listPhenomenon.add(phenomenon);
                }
                if (NumberUtil.isNotNullOrZero(phenId)) {
                    listPhenomenonFault.add(phenomenonFault);
                    listPhenomenonMaintain.add(phenomenonMaintain);
                }
            } catch (Exception ex) {
                log.info("数据解析错误，错误={}", ex);
                stringBuilder.append("第[" + (i) + "]行");
                if (insideMsg != null && insideMsg.length() > 0) {
                    stringBuilder.append(insideMsg);
                }
                stringBuilder.append("，数据解析错误 异常信息：" + ex.getMessage() + "。</br>");
                continue;
            }
        }
        phenomenonService.insertBatchById(listPhenomenon);
        phenomenonFaultService.insertBatch(listPhenomenonFault);
        phenomenonMaintainService.insertBatch(listPhenomenonMaintain);
        return stringBuilder;
    }

    /**
     * 组装消息
     *
     * @param insideMsg
     * @param msg
     * @return
     */
    private StringBuilder buildMsg(StringBuilder insideMsg, String msg) {
        if (insideMsg.length() > 0) {
            insideMsg.append("，");
        }
        insideMsg.append(msg);
        return insideMsg;
    }
}

